package com.easyCode.dataMock;

import com.baomidou.mybatisplus.annotation.TableField;
import com.easyCode.dataMock.anno.FieldMock;
import com.easyCode.dataMock.anno.TableMock;
import com.easyCode.util.ReflectionUtils;
import com.easyCode.util.StringUtil;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 负责解析对象,封装为TableMockInfo
 *
 * @author 大忽悠
 * @create 2023/1/18 12:23
 */
public class MockMapper {

    public static List<TableMockInfo> mapper(Object... obj) {
        List<TableMockInfo> tableMockInfoList = new ArrayList<>(obj.length);
        for (Object o : obj) {
            if (!skipObjIfNeed(o)) {
                tableMockInfoList.add(doMapper(o));
            }
        }
        return tableMockInfoList;
    }

    private static boolean skipObjIfNeed(Object o) {
        return !(AnnotationUtils.isCandidateClass(o.getClass(), TableMock.class)
                && AnnotationUtils.isCandidateClass(o.getClass(), TableField.class));
    }

    private static TableMockInfo doMapper(Object o) {
        TableMock tableMock = AnnotationUtils.findAnnotation(o.getClass(), TableMock.class);
        TableMockInfo tableMockInfo = new TableMockInfo();
        tableMockInfo.setMockNum(tableMock.mockNum());
        tableMockInfo.setTableName(StringUtil.isNullOrEmpty(tableMock.tableName()) ? StringUtil.camelToUnderline(o.getClass().getSimpleName()) : tableMock.tableName());
        tableMockInfo.setFieldMockInfoList(getFieldMockInfoList(o));
        return tableMockInfo;
    }

    private static List<FieldMockInfo> getFieldMockInfoList(Object o) {
        List<FieldMockInfo> fieldMockInfoList=new ArrayList<>(o.getClass().getDeclaredFields().length);
        for (Field field : ReflectionUtils.getAllDeclaredFileds(o.getClass())) {
             if(!skipFieldIfNeed(field)){
                 fieldMockInfoList.add(getFieldMockInfo(field));
             }
        }
        return fieldMockInfoList;
    }

    private static boolean skipFieldIfNeed(Field field) {
          return !field.isAnnotationPresent(FieldMock.class);
    }

    private static FieldMockInfo getFieldMockInfo(Field field) {
        FieldMock fieldMock = field.getAnnotation(FieldMock.class);
        FieldMockInfo fieldMockInfo = new FieldMockInfo();
        fieldMockInfo.setFieldName(StringUtil.isNullOrEmpty(fieldMock.fieldName())?StringUtil.camelToUnderline(field.getName()):fieldMock.fieldName());
        fieldMockInfo.setRule(fieldMock.rule());
        fieldMockInfo.setExtra(fieldMock.extra());
        return fieldMockInfo;
    }
}
